#include <vector>
#include <string>
#include <chrono>
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>
#include <bits/stdc++.h>

using namespace std;

constexpr uint64_t SHIFT_KB = 10ULL;
constexpr uint64_t SHIFT_MB = 20ULL;
constexpr uint64_t SHIFT_GB = 30ULL;

constexpr uint64_t operator"" _KB(unsigned long long count)
{
    return count * (1ULL << SHIFT_KB);
}

int func(int a) {
    int b = 10;
    return a * a + b;
}

static const size_t PAGE_SIZE = sysconf(_SC_PAGESIZE);

int main() {// 对齐地址并计算栈的有效范围
    uintptr_t currentStackPos = reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
    pthread_attr_t attr;
    void *stackAddr = nullptr;
    size_t size = 0;
    size_t guardSize = 0;
    int ret = 0;
    ret += pthread_attr_init(&attr);
    ret += pthread_getattr_np(pthread_self(), &attr);
    ret += pthread_attr_getguardsize(&attr, &guardSize);
    ret += pthread_attr_getstack(&attr, &stackAddr, &size);
    ret += pthread_attr_destroy(&attr);
    if (ret != 0) {
        cout << "Get current thread stack size failed";
        return 0;
    }

    cout << "guard size: " << guardSize << endl;
    if (guardSize < 4_KB) {
        guardSize = 4_KB;
    }

    cout << "stack size: " << size / 4096 << " KB" << endl;
    if (size <= 12_KB + 4_KB + guardSize) {
        cout << "too small stack size" << endl;
        return 0;
    }

    uintptr_t stackBegin = reinterpret_cast<uintptr_t>(stackAddr) + size - 128_KB;

    uintptr_t guard_page = currentStackPos & ~(PAGE_SIZE - 1);
    guard_page -= PAGE_SIZE;
    guard_page -= PAGE_SIZE;

    if (mprotect(reinterpret_cast<void*>(guard_page), PAGE_SIZE, PROT_NONE) != 0) {
        perror("mprotect failed");
        exit(1);
    }

    size_t protectSize = 64_KB;
    if (mprotect(reinterpret_cast<void*>(stackBegin), protectSize, PROT_NONE) != 0) {
        cout << hex << stackBegin << endl;
        std::cerr << "mprotect 失败: " << strerror(errno) << std::endl;
    }

    return func(5);
}